﻿using System;
using System.Windows.Media;
using System.Threading;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Microsoft.Phone.Controls.LocalizedResources;
///
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Threading;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Command;
using ScheduleMVVM.Model.PersistentFramework;
using ScheduleMVVM.Model.RuntimeFramework;
using ScheduleMVVM.Localization;

namespace ScheduleMVVM.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class RouteViewModel : ViewModelBase
    {
        private Mutex progressBarMutex;
        private Int32 progressBarCount;

        #region Binded properties
        private DateTime _enumerator_timestamp;
        private ObservableCollection<DataItemWrapper> _result;
        public ObservableCollection<DataItemWrapper> Result
        {
            get
            {
                if (LinkedAccessor.Result == null) return null;
                if (_result == null)
                {
                    _result = new ObservableCollection<DataItemWrapper>();
                }
                else if (_enumerator_timestamp > LinkedAccessor.SourceTimeStamp) return _result;
                else _result = new ObservableCollection<DataItemWrapper>();
                foreach (var i in LinkedAccessor.Result)
                {
                    if (i.Departure > DateTime.Now && _result.Count < Settings.Current.MaximumDisplayedResults) _result.Add(new DataItemWrapper(i));
                }
                _enumerator_timestamp = DateTime.Now;
                return _result;
            }
        }
        /// <summary>
        /// Data provider
        /// </summary>
        private AdvancedDataAccess LinkedAccessor;


        public String ErrorMessage
        { get; private set; }
        public String ApplicationTitle
        {
            get { return GeneralResource.ApplicationTitle.ToUpper(); }
        }
        public Boolean ProgressIndicatorStatus
        { get; private set; }
        public String ProgressIndicatorText
        {
            get;
            private set;
            //{
            //    return GeneralResource.ProgressIndicatorDownloadingText;
            //    return null;
            //}
        }
        public String PageTitle
        {
            get
            {
                return LinkedFavourite.Title;
            }
        }
        public Boolean IsSearch
        {
            get
            {
                if (LinkedFavourite == null) return false;
                return LinkedFavourite.InnerValue.IsSearch;
            }
        }
        public Boolean IsNotSearch
        {
            get { return !IsSearch; }
        }
        public String EditAppBarIconString
        {
            get
            {
                if (IsNotSearch) return GeneralResource.EditCommandString;
                else return AddToFavAppBarIconString;
            }
        }
        public String DeleteAppBarIconString
        {
            get { return GeneralResource.DeleteCommandString; }
        }
        public String PinAppBarIconString
        {
            get { return GeneralResource.PinCommandString; }
        }
        public String AddToFavAppBarIconString
        {
            get { return GeneralResource.AddFavPageTitle; }
        }
        public RelayCommand AddToFavouritesCommand
        {
            get
            {
                return new RelayCommand(delegate
                    {
                        ((App)App.Current).RootFrame.Navigate(new System.Uri("/AddFavouritePage.xaml", System.UriKind.Relative));
                    });
            }
        }
        public Uri SpecialIconButtonUri
        {
            get
            {
                if (IsSearch)
                {
                    return new Uri("/icons/appbar.favs.addto.rest.png", UriKind.Relative);
                }
                else
                {
                    return new Uri("/icons/appbar.edit.rest.png", UriKind.Relative);
                }
            }
        }
        public RelayCommand DeleteFavouriteAndExitViewCommand
        {
            get
            {
                return new RelayCommand(delegate
                {
                    Messenger.Default.Send<UpdateContextCommand>(new UpdateContextCommand()
                    {
                        Action = UpdateContextCommandType.DELETE,
                        Argument = LinkedFavourite.InnerValue
                    });
                    if(((App)App.Current).RootFrame.CanGoBack) ((App)App.Current).RootFrame.GoBack();
                });
            }
        }
        #endregion

        public RouteEntryWrapper LinkedFavourite
        { get; private set; }
        /// <summary>
        /// Initializes a new instance of the RepresentationTemplateViewModel class.
        /// </summary>
        public RouteViewModel()
        {
            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.
            }
            else
            {
                progressBarMutex = new Mutex(false, "__progressBar_Mutex");
                progressBarCount = 0;
                ProgressIndicatorText = String.Empty;
                ErrorMessage = String.Empty;
                MessengerInstance = GalaSoft.MvvmLight.Messaging.Messenger.Default;
                MessengerInstance.Register<DownloadCompletedMessage>(this, DownloadCompletedHandler);
                MessengerInstance.Register<DownloadErrorMessage>(this, DownloadErrorHandler);
                MessengerInstance.Register<DownloadCompletedMessage>(this, DispatchMessageFree);
                MessengerInstance.Register<DownloadErrorMessage>(this, DispatchMessageError);
                MessengerInstance.Register<DownloadInvokedMessage>(this, DispatchMessageBusy);
                MessengerInstance.Register<UpdateRouteViewCommand>(this, UpdateViewHandler);
                MessengerInstance.Register<UpdateTick>(this, delegate { _result = null; });
                MessengerInstance.Register<ListChangedMessage>(this, delegate { DispatcherHelper.CheckBeginInvokeOnUI(delegate { RaisePropertyChanged("PageTitle"); }); });
                MessengerInstance.Register<OnActivatedCommand>(this, delegate { DispatcherHelper.CheckBeginInvokeOnUI(delegate { RaisePropertyChanged("Result"); }); });
            }

        }
        private void DownloadCompletedHandler(DownloadCompletedMessage message)
        {
            ErrorMessage = String.Empty;
            DispatcherHelper.CheckBeginInvokeOnUI(delegate
            {
                RaisePropertyChanged("Result");
                RaisePropertyChanged("ErrorMessage");
            });
        }
        private void DownloadErrorHandler(DownloadErrorMessage message)
        {
            switch (message.Cause)
            {
                case ErrorCause.PARSE_ERROR:
                    ErrorMessage = GeneralResource.ErrorMessageParseError;
                    break;
                case ErrorCause.DOWNLOAD_ERROR:
                    ErrorMessage = GeneralResource.ErrorMessageDownloadError;
                    break;
                case ErrorCause.NO_TRANSITION:
                    ErrorMessage = GeneralResource.ErrorMessageNoTransitionError;
                    break;
                default:
                    ErrorMessage = GeneralResource.ErrorMessageUnknownError;
                    break;
            }
            DispatcherHelper.CheckBeginInvokeOnUI(delegate
            {
                RaisePropertyChanged("ErrorMessage");
            });
        }
        private void UpdateViewHandler(UpdateRouteViewCommand message)
        {
            ErrorMessage = String.Empty;
            RaisePropertyChanged("ErrorMessage");
            RaisePropertyChanged("SpecialIconButtonUri");
            RaisePropertyChanged("EditAppBarIconString");
            // Check if there are changes
            if (LinkedFavourite == message.NewEntry)
            {
                RaisePropertyChanged("Results");
                RaisePropertyChanged("IsNotSearch");
                return;
            }
            // There ARE changes, continue
            LinkedFavourite = message.NewEntry;
            _result = null;
            LinkedAccessor = new AdvancedDataAccess(LinkedFavourite.InnerValue);
            RaisePropertyChanged("Results");
            RaisePropertyChanged("LinkedFavourite");
            RaisePropertyChanged("IsNotSearch");
        }
        private void DispatchMessageBusy(DownloadInvokedMessage message)
        {
            DownloadStateChange(1);
        }
        private void DispatchMessageFree(DownloadCompletedMessage message)
        {
            DownloadStateChange(-1);
        }
        private void DispatchMessageError(DownloadErrorMessage message)
        {
            DownloadStateChange(-1);
        }
        private void DownloadStateChange(Int16 inc)
        {
            progressBarMutex.WaitOne();
            // Start critical section
            progressBarCount += inc;
            UpdateProgressIndicator(progressBarCount != 0);
            // End critical sectio
            progressBarMutex.ReleaseMutex();
        }
        private void UpdateProgressIndicator(Boolean state)
        {
            ProgressIndicatorStatus = state;
            if (state)
                ProgressIndicatorText = GeneralResource.ProgressIndicatorDownloadingText;
            else
                ProgressIndicatorText = String.Empty;
            DispatcherHelper.CheckBeginInvokeOnUI(delegate
            {
                RaisePropertyChanged("ProgressIndicatorStatus");
                RaisePropertyChanged("ProgressIndicatorText");
            });
        }
        ////public override void Cleanup()
        ////{
        ////    // Clean own resources if needed

        ////    base.Cleanup();
        ////}
    }
}